package com.bc.bcapi.service;

import com.bc.bcapi.dao.*;
import com.bc.bcapi.utils.Ognl;
import com.bc.bcapi.utils.web3j.ERC20TransactionModel;
import com.bc.bcapi.utils.web3j.Util;
import com.bc.bccore.web3j.WalletService;
import com.bc.bcmodel.domain.*;
import com.bc.commonentity.enums.SeqNameEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;

@Service
public class TransGasService {
    @Resource
    T_Inner_transMapper t_inner_transMapper;
    @Resource
    T_BalanceMapper t_balanceMapper;
    @Resource
    T_Account_logMapper t_account_logMapper;
    @Resource
    T_Erc_contractMapper t_erc_contractMapper;
    @Resource
    T_SequenceService t_sequenceService;
    @Resource
    T_TxhashMapper t_txhashMapper;
    @Resource
    T_User_walletMapper t_user_walletMapper;

    private static final Logger LOGGER = LoggerFactory.getLogger(TransGasService.class);

    public void transGas(T_Inner_transModel transGasModel, ERC20TransactionModel transactionModel, boolean status) throws Exception {
        int s = status ? 1 : 2;
        record(transGasModel, transactionModel, s);
        //发起转冷
        if (status) transCold(transGasModel);
    }
    /*
    1. T_Inner_transModel 更新状态
    2. t_balance 收入 y
    3. t_balance 支出矿工费
    */
    @Transactional(rollbackFor = {
            Exception.class}, isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public void record(T_Inner_transModel transColdModel, ERC20TransactionModel transactionModel, int status) throws Exception {
        transColdModel.setPay_status(status);
        if (t_inner_transMapper.update(transColdModel) <= 0) throw new Exception("update inner trans status error");

        T_BalanceModel gasBalanceModel = new T_BalanceModel();
        gasBalanceModel.setToken_type(Util.getETHID());
        gasBalanceModel.setTrans_type("间接转冷gas支出");
        gasBalanceModel.setTrans_id(transColdModel.getInner_trans_id());
        gasBalanceModel.setValue(transColdModel.getGas_account());

        t_balanceMapper.insert(gasBalanceModel);

        if (status == 2) LOGGER.info("间接转冷失败");
    }

    @Transactional(rollbackFor = {
            Exception.class}, isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public void transCold(T_Inner_transModel transGasModel) throws Exception {
        BigInteger reCharge_log_id = transGasModel.getRecharge_log_id();
        T_Account_logModel reCharge_logModel = t_account_logMapper.selectByPrimaryKey(reCharge_log_id);

        BigDecimal reChargeValue = reCharge_logModel.getAmount();
        String contract_id = reCharge_logModel.getAmount_type();
        T_Erc_contractModel contractModel = t_erc_contractMapper.selectContractByContractID(contract_id);
        String contract_address = contractModel.getContract_address();

        BigDecimal inner_trans_value = transGasModel.getActual_account();
        BigInteger inner_trans_value_wei = Util.convertEth2Wei(inner_trans_value);
        BigInteger gasLimit = Util.getCONTRACTGASLIMIT();
        BigInteger gasPrice = inner_trans_value_wei.divide(gasLimit);
        BigInteger reChargeValueWei = Util.Token2Wei(reChargeValue, contractModel.getDigit());

        String from = transGasModel.getDest_address();
        String to = Util.getColdWalletAddress();

        T_User_walletModel t_user_walletModel = t_user_walletMapper.getWalletByAddress(from);
        String spk = t_user_walletModel.getPrivate_key();
        String salt = t_user_walletModel.getUser_id();
        String pk = Util.getUserPk(spk, salt);


        //t_inner_trans
        T_Inner_transModel transColdModel = new T_Inner_transModel();
        String inner_tran_id = t_sequenceService.genSequence(SeqNameEnum.INNER_TRANS_ID);
        transColdModel.setInner_trans_id(inner_tran_id);
        transColdModel.setWithdraw_account(reChargeValue);
        transColdModel.setToken_name(contract_id);
        transColdModel.setPay_status(0);
        transColdModel.setGas_account(Util.convertWei2Eth(inner_trans_value_wei));
        transColdModel.setActual_account(reChargeValue);
        transColdModel.setPay_address(from);
        transColdModel.setDest_address(to);
        transColdModel.setRecharge_log_id(reCharge_logModel.getId());
        if (t_inner_transMapper.insert(transColdModel) < 1)
            throw new Exception("insert into inner_trans error");

        //t_txhash
        String txhash = WalletService.getInstance().sendContractTransaction(pk, contract_address, to, gasPrice, gasLimit, reChargeValueWei);
        if (Ognl.isBlank(txhash)) throw new Exception("contract send cold wallet error");

        T_TxhashModel txhashModel = new T_TxhashModel();
        txhashModel.setTxhash(txhash);
        txhashModel.setWithdraw_id(inner_tran_id);
        txhashModel.setTranstype(2);
        t_txhashMapper.insert(txhashModel);
    }

}
